// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Author: wsfuyibing <682805@qq.com>
// Date: 2024-12-10

package filter

import (
	"strings"
)

// Key
// is a type name for condition field name.
type Key string

// Seek seeks a value in given data, returns an any format value if defined.
func (o Key) Seek(data map[string]any) (v any, has bool) {
	var (
		l  = strings.Split(o.String(), ".")
		n  = len(l) - 1
		ok bool
	)

	// Iterate field name that joined with dot string.
	for i, s := range l {
		// Break if given name not found in data.
		if v, has = data[s]; !has {
			break
		}

		// Break loop if current part is end of the key.
		if i == n {
			break
		}

		// Reset data for next part, Break loop if found value not a map data.
		if data, ok = v.(map[string]any); !ok {
			break
		}
	}
	return
}

func (o Key) String() string { return string(o) }

// KeyKind
// is a type name for condition field kind.
type KeyKind string

const (
	KeyKindCounter KeyKind = "#" // #key == 1 (WHERE COUNT(key) == 1)
	KeyKindVarName KeyKind = "." // .key == "value" ( WHERE key == "value")
	KeyKindBoolean KeyKind = "@" // @key == true ()

	undefinedKeyKind KeyKind = ""
)

func (o KeyKind) Defaulter() KeyKind {
	if o.Undefined() {
		return KeyKindVarName
	}
	return o
}

func (o KeyKind) IsBoolean() bool { return o == KeyKindBoolean }
func (o KeyKind) IsCount() bool   { return o == KeyKindCounter }
func (o KeyKind) IsVarName() bool { return o == KeyKindVarName }

func (o KeyKind) String() string  { return string(o) }
func (o KeyKind) Undefined() bool { return o == undefinedKeyKind }
